//
// Created by pzw on 24-3-12.
//

#include "ModifySeq.h"

void ModifySeq::std_transform_toupper(std::string &text) {
    std::transform(text.begin(), text.end(), text.begin(), toupper);
}

void ModifySeq::std_copy_stream(std::list<Club> &lc, std::ostream &os) {
    std::copy(lc.begin(), lc.end(), std::ostream_iterator<Club>(os));
}

void ModifySeq::std_copy_vec(const std::vector<char> &vs, std::vector<char> &v) {
    using namespace std;
    copy(vs.begin(), vs.end(), v.begin());
    copy(vs.begin(), vs.end(), back_inserter(v));
}

void ModifySeq::std_unique_vec(std::list<char> &ls, std::vector<char> &vs) {
    /* 这段代码将ls的元素拷贝到s中，过程中会删除连续重复的元素，所以我们需要用sort先把重复的排成连续一起的 */
    ls.sort();
    std::unique_copy(ls.begin(), ls.end(), std::back_inserter(vs));
}

/**
 * 到这里才体会到C++的模板的牛逼之处：
 *    1. 你完全可以定义一个不知名的模板参数，你可以让这个模板参数调用任何函数；
 *    2. 接着，你可以用模板进行任何操作，即使目前这个模板类型找不到任何成员；
 *    3. 最后，只要你最终能够传入一个具体的类型，只要这个类型满足这个模板的调用函数，就可以执行；
 *    这才是真正的模板编程，不是java之流可以比拟的；
 *
 * @tparam Container - 任意容器类型
 * @param cn         - 任意容器类型实例
 * C++的模板，很像是你完全可以在没有任何产品的情况下，先把产品应该遵循的协议给定义出来，而这之后
 * 生产的产品，都应该遵循这个模板协议，实现模板协议中定义好的协议；
 */
template<typename Container>
void ModifySeq::std_unique_erase_vec(Container &cn) {
    using namespace std;
    sort(cn.begin(), cn.end());             //排序
    auto it = unique(cn.begin(), cn.end()); //紧凑存储
    cn.erase(it, cn.end());                 //收缩
}

/**
 * 到这里才体会到C++的模板的牛逼之处：
 *    1. 你完全可以定义一个不知名的模板参数，你可以让这个模板参数调用任何函数；
 *    2. 接着，你可以用模板进行任何操作，即使目前这个模板类型找不到任何成员；
 *    3. 最后，只要你最终能够传入一个具体的类型，只要这个类型满足这个模板的调用函数，就可以执行；
 *    这才是真正的模板编程，不是java之流可以比拟的；
 *
 * @tparam Container - 任意容器类型
 * @param cn         - 任意容器类型实例
 * C++的模板，很像是你完全可以在没有任何产品的情况下，先把产品应该遵循的协议给定义出来，而这之后
 * 生产的产品，都应该遵循这个模板协议，实现模板协议中定义好的协议；
 */
template<typename Container>
void ModifySeq::std_remove_vec(Container &cn) {
    using namespace std;
    cout << ": std_remove_vec origin: cn = " << cn << endl;         // 输出 *CamelCase*IsUgly*
    auto it = remove(cn.begin(), cn.end(), '*');
    copy(cn.begin(), it, ostream_iterator<char>{cout});          // 输出 CamelCaseIsUgly
    cout << endl << ": std_remove_vec remove: cn =" << cn << endl;  // 输出 CamelCaseIsUgly*
}

void ModifySeq::std_next_permutation_vec(std::vector<char> &vs) {
    using namespace std;
    while (next_permutation(vs.begin(), vs.end())) {
        cout << "std_next_permutation_vec: vs = " << vs[0] << vs[1] << vs[2] << endl;
    }
}

void ModifySeq::std_fill_vec(std::array<int, 900> v2, std::vector<int> &v3) {
    using namespace std;
    int v1[900];
    fill(begin(v1), end<>(v1), 99);
    generate(begin(v2), end(v2), Rand_int{});
    generate_n(ostream_iterator<int>{cout}, 200, Urand{100});
    fill_n(back_inserter(v3), 20, 99);
}

void ModifySeq::std_swap_vec(std::vector<int> &vs, int *ptr) {
    std::swap_ranges(vs.begin(), vs.end(), ptr);
}

int ModifySeq_main() {
    std::string text{"Why waste time learning, when ignorance is instantaneous?"};
    ModifySeq::std_transform_toupper(text);
    std::cout << "ModifySeq_main: std_transform_toupper, text = " << text << std::endl;

    std::list<Club> clubList;
    clubList.push_back(Club("ClubA"));
    clubList.push_back(Club("ClubB"));
    clubList.push_back(Club("ClubC"));
    std::ostream &os = std::cout;               // 输出到控制台
    std::ofstream ofs("std_copy_stream.txt"); // 输出到文件
    std::ostream &os2 = ofs;
    ModifySeq::std_copy_stream(clubList, os);
    ModifySeq::std_copy_stream(clubList, os2);

    std::vector<char> v{0};
    ModifySeq::std_copy_vec({'0', '1', '2', '3', '4', '5', '6', '7'}, v);
    std::cout << std::endl;
    for (auto it = v.begin(); it != v.end(); it++) {
        std::cout << "ModifySeq_main: std_copy_vec, v = " << *it << std::endl;
    }

    std::vector<char> vs{-1};
    std::list<char> ls{'0', '1', '2', '3', '4', '5', '6', '7', '0', '1', '2', '3', '4', '5', '6', '7'};
    ModifySeq::std_unique_vec(ls, vs);
    for (auto it = vs.begin(); it != vs.end(); it++) {
        std::cout << "ModifySeq_main: std_unique_vec, vs = " << *it << std::endl;
    }

    std::vector<char> vss{'0', '1', '2', '3', '4', '5', '6', '7', '0', '1', '2', '3', '4', '5', '6', '7'};
    ModifySeq::std_unique_erase_vec(vss);
    for (auto it = vs.begin(); it != vs.end(); it++) {
        std::cout << "ModifySeq_main: std_unique_erase_vec, vss = " << *it << std::endl;
    }

    std::string cn{"*CamelCase*IsUgly*"};
    ModifySeq::std_remove_vec(cn);

    std::vector<char> vchar{'a', 'b', 'c'};
    ModifySeq::std_next_permutation_vec(vchar);

    std::vector<int> vint{0};
    ModifySeq::std_fill_vec(std::array<int, 900>(), vint);

    std::vector<int> vints = {0, 1, 2, 3, 4, 5, 6, 7};
    int arr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
    int *pInt = arr;
    ModifySeq::std_swap_vec(vints, pInt);
    std::cout << std::endl;
    int in = 0;
    auto it = vints.begin();
    while (in < 8) {
        std::cout << "ModifySeq_main: std_swap_vec, pInt=" << *pInt++ << std::endl;
        in++;
    }
    int inc = 0;
    while (inc < 8) {
        std::cout << "ModifySeq_main: std_swap_vec, vints=" << *it++ << std::endl;
        inc++;
    }

    return 0;
}